package com.alibaba.service.impl;

import com.alibaba.model.entity.Goods;
import com.alibaba.service.GoodsService;
import com.alibaba.mapper.GoodsMapper;
import com.alibaba.utils.BizException;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RedissonClient;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;

@Slf4j
@Service
public class GoodsServiceImpl implements GoodsService {

    @Resource
    private GoodsMapper goodsMapper;

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @Resource
    private RBloomFilter<String> goodsBloomFilter;

    @Resource
    private RedissonClient redissonClient;


    private static final long CACHE_EXPIRE_MINUTES = 10;
    private static final String CACHE_KEY_PREFIX = "goods:id:";
    private static final String BLOOM_KEY = "goods:bloomfilter";
    private static final String BLOOM_SET_KEY = "goods:bloom:set";

    @Override
    public void addGoods(Goods goods) {
        val rows = goodsMapper.insert(goods);
        if (rows == 0) {
            throw new BizException("Failed to add goods");
        }

        String idStr = String.valueOf(goods.getId());
        // 添加到 BloomFilter
        goodsBloomFilter.add(idStr);
        // 同时维护 Redis Set
        redisTemplate.opsForSet().add(BLOOM_SET_KEY, idStr);

        log.info("[GoodsService] Added new goods to BloomFilter and Set, id: {}", goods.getId());
    }

    @Override
    public boolean updateGoods(Goods goods) {
        Long goodsId = goods.getId();
        if (goodsId == null) {
            throw new RuntimeException("Goods ID cannot be null");
        }

        String redisKey = getGoodsRedisKey(goodsId);

        // 1️⃣ 删除缓存，保证后续读取不会拿到旧数据
        redisTemplate.delete(redisKey);
        log.info("[GoodsService] Deleted cache before DB update, key: {}", redisKey);

        // 2️⃣ 更新数据库中的商品信息
        int rows = goodsMapper.updateById(goods);
        if (rows == 0) {
            throw new RuntimeException("Failed to update goods in DB, id: " + goodsId);
        }
        log.info("[GoodsService] Updated DB for goods id: {}", goodsId);

        // 3️⃣ 延迟再删除一次缓存，防止高并发场景下缓存恢复为旧值
        new Thread(() -> {
            try {
                Thread.sleep(200); // 延迟 200ms，可根据业务情况调整
                redisTemplate.delete(redisKey);
                log.info("[GoodsService] Deleted cache after delay, key: {}", redisKey);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                log.error("[GoodsService] Delay delete cache interrupted", e);
            }
        }).start();

        // 4️⃣ 布隆过滤器无需更新，因为商品 ID 不会改变

        return true;
    }



    @Override
    public List<Goods> listAvailableGoods() {
        val goodsQueryWrapper = new QueryWrapper<Goods>().eq("status", 1).orderByAsc("create_time");
        List<Goods> goodsList = goodsMapper.selectList(goodsQueryWrapper);
        if (goodsList == null || goodsList.isEmpty()) {
            throw new RuntimeException("No available goods found");
        }
        return goodsList;
    }

    /**
     * 获取 Redis Set 中维护的所有商品 ID（布隆过滤器的调试集合）
     * 仅用于调试/运维，不建议高频调用
     */
    @Override
    public List<String> listGoodsInBloomFilter() {
        // 从 Redis 读取 Set 中的所有成员
        Set<Object> idSet = redisTemplate.opsForSet().members(BLOOM_SET_KEY);
        if (idSet == null || idSet.isEmpty()) {
            log.info("[GoodsService] Bloom Set is empty");
            return Collections.emptyList();
        }

        // 转换为字符串列表返回
        List<String> result = new ArrayList<>(idSet.size());
        for (Object id : idSet) {
            result.add(id.toString());
        }

        log.info("[GoodsService] Bloom Set contains {} goods IDs", result.size());
        return result;
    }

    public Goods getGoodsById(Long id) {
        RBloomFilter<String> bloomFilter = redissonClient.getBloomFilter(BLOOM_KEY);

        // 先检查布隆过滤器
        String idStr = String.valueOf(id);
        // 先检查布隆过滤器，快速判断可能不存在
        if (!bloomFilter.contains(idStr)) {
            log.info("[GoodsService] BloomFilter indicates non-existence, id: {}", id);
            throw new BizException("bloomFilter Goods not found, id: " + id);
        }

        // 尝试从缓存读取
        String cacheKey = CACHE_KEY_PREFIX + id;
        Goods goods = (Goods) redisTemplate.opsForValue().get(cacheKey);
        if (goods != null) return goods;

        // 缓存未命中，查询数据库
        goods = goodsMapper.selectById(id);
        if (goods != null) {
            // 写入缓存，设置过期时间
            redisTemplate.opsForValue().set(cacheKey, goods, Duration.ofMinutes(10));
            log.info("[GoodsService] Added goods in Redis, id: {}", id);
            // 添加到 BloomFilter 和 Set
            bloomFilter.add(idStr);
            redisTemplate.opsForSet().add(BLOOM_SET_KEY, idStr);

            log.info("[GoodsService] Added goods to BloomFilter, id: {}", id);
            return goods;
        } else {
            log.warn("[GoodsService] DB miss, id: {}", id);
            throw new BizException("DB Goods not found, id: " + id);
        }
    }

    /**
     * Redis Key 生成器
     * key 格式: goods:id:{id}:info
     */
    private String getGoodsRedisKey(Long id) {
        return String.format("goods:id:%d:info", id);
    }
}
